<!---
	Copyright 2010 Edward Trudeau, Jeremy Battle
    This software is freely available under the MIT License: http://www.opensource.org/licenses/mit-license.php
    http://ayc.googlecode.com
    
--->

<cfcomponent displayname="formUtils" output="no" hint="Utilities for handling dynamic form building and parameterization">
	
    <cfset variables.dsn = "" />
    <cfset variables.FieldService = "" />
    
    <cffunction name="init" access="public" returntype="aycFormUtils">
    	<cfargument name="DSN" type="string" required="yes" hint="The data source name to use with this instance of the form utilities" />
		<cfargument name="FieldService" type="ayc.cfc.Field.FieldService" required="true" />
        
        <cfset variables.dsn = arguments.dsn />
        <cfset variables.FieldService = arguments.FieldService />
        
		<cfreturn this>
	</cffunction>
    
    <cffunction name="setFormVals" returntype="boolean" output="no" hint="Sets the default or current values of form fields">
    	<cfargument name="Page" type="string" required="yes" hint="The page name or id to load" />
        <cfargument name="item" type="any" required="no" hint="A bean to load." />
        
        <cfset var aFields = "" />
        <cfset var iii 		 = "" />
        <cfset var nextField = "" />
        
        <cfif structKeyExists(arguments, "Page")>
        	<cfset aFields = variables.FieldService.getFieldsByPage(arguments.Page) />
            <cfloop from="1" to="#arrayLen(aFields)#" index="iii">
                <cfloop list="#getFormFields(aFields[iii])#" index="nextField">
					<cfif structKeyExists(arguments, "item") AND isObject(arguments.item)>
						<cfif NOT structKeyExists(form, "#nextField#")>
                            <cfset form["#nextField#"] = evaluate("arguments.item.get#nextField#()") />
                        </cfif>
                    <cfelse>
                    	<cfif NOT structKeyExists(form, "#nextField#")>
							<cfset form["#nextField#"] = aFields[iii].getDefaultsTo() />
                        </cfif>
                    </cfif>
                </cfloop>
            </cfloop>
        </cfif>
        
        <cfreturn true />
        
    </cffunction>
    
    <cffunction name="stripFormVals" returntype="struct" output="no" hint="Clears form variables that have no value in preparation for object creation using the form scope. Non-empty values are preserved, even complex ones.">
    	<cfargument name="inForm" type="struct" required="yes" hint="The form scope that must be minified" />
        
        <cfset var outForm = duplicate(arguments.inForm) />
        <cfset var nextMember = "" />
        
        <cfloop collection="#outForm#" item="nextMember">
        	<cfif isSimpleValue(outForm["#nextMember#"]) AND outForm["#nextMember#"] EQ "">
            	<cfset structDelete(outForm, nextMember) />
            </cfif>
        </cfloop>
        
        <cfreturn outForm />
        
    </cffunction>
    
    <cffunction name="getAllFields" returntype="string" output="no" hint="Retrieves a list of form field names from the array of field metadata">
    	<cfargument name="fieldArray" type="array" required="yes" hint="The Form.Fields array containing all metadata for the form fields" />
    	
        <cfset var fieldList = "" />
        <cfset var iii = "" />
        
        <cfloop from="1" to="#arrayLen(arguments.fieldArray)#" index="iii">
			<cfset fieldList = listAppend(fieldList, getFormFields(arguments.FieldArray[iii])) />
        </cfloop>
        
        <cfreturn fieldList />
    </cffunction>    
    
    <cffunction name="findField" access="private" hint="Finds the index in the field meta array that has the corresponding attribute" returntype="numeric">
    	<cfargument name="fields" type="array" required="yes" hint="The array of field metadata structures" />
        <cfargument name="fieldName" type="string" required="yes" hint="The name of the object to find" />
        
        <cfset var iii = "" />
        
        <cfloop from="1" to="#arrayLen(arguments.fields)#" index="iii">
        	<cfif arguments.fields[iii].fieldName EQ arguments.fieldName>
            	<cfreturn iii />
            </cfif>
        </cfloop>
        
        <cfreturn 0 />
    </cffunction>
    
    <cffunction name="getFormFields" returntype="string" output="no" hint="Retrieves the list of form fields for a given field metadata structure">
    	<cfargument name="Field" type="struct" required="yes" hint="The structure containing the field metadata" />
        
        <cfset var fieldList = "" />
        <cfset var jjj = "" />
        
        <cfif arguments.Field.getFieldType() EQ "Likert">
            <cfloop from="1" to="#arrayLen(arguments.Field.getQuestions())#" index="jjj">
                <cfset fieldList = listAppend(fieldList, arguments.Field.getFieldName()&"_#jjj#") />
            </cfloop>
        <cfelseif  arguments.Field.getFieldType() EQ "Checkbox">
            <cfloop from="1" to="#arrayLen(arguments.Field.getOptions())#" index="jjj">
                <cfset fieldList = listAppend(fieldList, arguments.Field.getFieldName()&"_#jjj#") />
            </cfloop>
        <cfelseif  arguments.Field.getFieldType() EQ "Checkbox Other">
            <cfloop from="1" to="#arrayLen(arguments.Field.getOptions())#" index="jjj">
                <cfset fieldList = listAppend(fieldList, arguments.Field.getFieldName()&"_#jjj#") />
            </cfloop>
            <cfset fieldList = listAppend(fieldList,  arguments.Field.getFieldName()&"_other") />
            <cfset fieldList = listAppend(fieldList,  arguments.Field.getFieldName()&"_otherVal") />
        <cfelseif  arguments.Field.getFieldType() EQ "Radio Other">
            <cfset fieldList = arguments.Field.getFieldName() />
            <cfset fieldList = listAppend(fieldList,  arguments.Field.getFieldName()&"_otherVal") />
        <cfelse>
            <cfset fieldList = arguments.Field.getFieldName() />
        </cfif>
        
        <cfreturn fieldList />
    </cffunction>    
    
</cfcomponent>

